#include "Player.h"
#include <QDebug>
#include <QStringList>

Player::Player(const QString &name)
  : mName(name), mNumGames(0), mNumPointsScored(0),
    mWins(0), mLosses(0), mEscalations(0),
    mBagsMade(0), mCancellations(0), mRoundsPlayed(0),
    mOneAndOuts(0), mRating(100.0)
{
}

const QString& Player::name() const
{
  return mName;
}

unsigned int Player::games() const
{
  return mNumGames;
}

unsigned int Player::pointsScored() const
{
  return mNumPointsScored;
}

unsigned int Player::wins() const
{
  return mWins;
}

unsigned int Player::losses() const
{
  return mLosses;
}

unsigned int Player::escalations() const
{
  return mEscalations;
}

unsigned int Player::cancellations() const
{
  return mCancellations;
}

unsigned int Player::bagsMade() const
{
  return mBagsMade;
}

float Player::rating() const
{
  return mRating;
}

float Player::ballShotPct() const
{
  if (mRoundsPlayed == 0) return 0.0;
  return (mNumPointsScored-(mBagsMade*2))/(mRoundsPlayed*4.0);
}

float Player::bagShotPct() const
{
  if (mRoundsPlayed == 0) return 0.0;
  return mBagsMade/(mRoundsPlayed*1.0);
}

int Player::rounds() const
{
  return mRoundsPlayed;
}

void Player::setGames(int games)
{
  mNumGames = games;
}

void Player::setPointsScored(int ps)
{
  mNumPointsScored = ps;
}

void Player::setWins(int wins)
{
  mWins = wins;
}

void Player::setLosses(int losses)
{
  mLosses = losses;
}

void Player::setEscalations(int escalations)
{
  mEscalations = escalations;
}

void Player::setCancellations(int cancellations)
{
  mCancellations = cancellations;
}

void Player::setBagsMade(int bagsmade)
{
  mBagsMade = bagsmade;
}

void Player::setRating(float rating)
{
  mRating = rating;
}

void Player::setRoundsPlayed(int rp)
{
  mRoundsPlayed = rp;
}

bool Player::addGame(const Game& game)
{
  if (game.forfeit())
  {
    return (game.forfeiter() == mName);
  }
  else
  {
    bool useTurn(game.player1() == mName), firstTurn(true), cancel(false);
    int turns(0);
    unsigned int previousTurnScore(0);
    ++mNumGames;
    foreach(Game::Turn t, game.turns())
    {
      cancel = false;
      if (useTurn)
      {
        ++mRoundsPlayed;
        mNumPointsScored += t.points;
        if (t.bagWasMade) ++mBagsMade;
        if (!firstTurn)
        {
          if (previousTurnScore < t.points && previousTurnScore > 0)
          {
            ++mEscalations;
          }
          else if (previousTurnScore == t.points && t.points > 0)
          {
            ++mCancellations;
            cancel = true;
          }
          else if (previousTurnScore > t.points)
          {
            ++mLosses;
            return false;
          }
        }
      }
      else if (!firstTurn)
      {
        if (previousTurnScore > t.points)
        {
          ++mWins;
          if (turns == 1) ++mOneAndOuts;
          return true;
        }
        else if (previousTurnScore == t.points && t.points > 0)
        {
          cancel = true;
        }
      }
      useTurn = !useTurn;
      firstTurn = cancel;
      previousTurnScore = t.points;
      ++turns;
    }
    return false;
  }
}

void Player::adjustRating(const Player &op, bool didWin, int factor)
{
  if (didWin)
  {
    mRating += (op.mRating * factor)/(op.mRating > mRating?mRating:op.mRating);
  }
  else
  {
    mRating -= (mRating * factor)/(op.mRating > mRating?mRating:op.mRating);
  }
  if (mRating < 10.0) mRating = 10.0;
}

bool Player::operator <(const Player& rhs) const
{
  if (mRating < rhs.mRating) return true;
  else if (mRating > rhs.mRating) return false;
  else
  {
    return mNumGames < rhs.mNumGames;
  }
}

QString Player::toString() const
{
  return mName + ": Games=" + QString::number(mNumGames) +
         " Wins=" + QString::number(mWins) +
         " Losses=" + QString::number(mLosses) +
         " Bags=" + QString::number(mBagsMade) +
         " Points=" + QString::number(mNumPointsScored) +
         " Escalations=" + QString::number(mEscalations) +
         " Cancellations=" + QString::number(mCancellations) +
         " Rating=" + QString::number(mRating) +
         " Ball-Shot%=" + QString::number((mNumPointsScored-(mBagsMade*2))/(mRoundsPlayed*4.0)) +
         " Bag-Shot%=" + QString::number(mBagsMade/(mRoundsPlayed*1.0)) +
         " Rounds=" + QString::number(mRoundsPlayed);// +
         " One-and-Outs=" + QString::number(mOneAndOuts);
}

QString Player::toFileString() const
{
  return mName + "," + QString::number(mNumGames) +
         "," + QString::number(mWins) +
         "," + QString::number(mLosses) +
         "," + QString::number(mBagsMade) +
         "," + QString::number(mNumPointsScored) +
         "," + QString::number(mEscalations) +
         "," + QString::number(mCancellations) +
         "," + QString::number(mRating) +
         "," + QString::number((mNumPointsScored-(mBagsMade*2))/(mRoundsPlayed*4.0)) +
         "," + QString::number(mBagsMade/(mRoundsPlayed*1.0)) +
         "," + QString::number(mRoundsPlayed) +
         "," + QString::number(mOneAndOuts);
}

void Player::fromString(const QString &data)
{
  QList<QString> values(data.split(","));
  if (values.count() == 13)
  {
    mName = values.at(0);
    mNumGames = values.at(1).toInt();
    mWins = values.at(2).toInt();
    mLosses = values.at(3).toInt();
    mBagsMade = values.at(4).toInt();
    mNumPointsScored = values.at(5).toInt();
    mEscalations = values.at(6).toInt();
    mCancellations = values.at(7).toInt();
    mRating = values.at(8).toFloat();
    mRoundsPlayed = values.at(11).toInt();
    mOneAndOuts = values.at(12).toInt();
  }
}
